﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

namespace FrameWork.Classes.Data
{
    // Summary:
    //     Wraps and creates an object that you can use as a binding source.
    public class ObjectDataProvider : DataSourceProvider
    {
        // Summary:
        //     Initializes a new instance of the System.Windows.Data.ObjectDataProvider
        //     class.
        public ObjectDataProvider()
        {
            State = DataSourceState.Ready;
        }

        // Summary:
        //     Gets the list of parameters to pass to the constructor.
        //
        // Returns:
        //     The list of parameters to pass to the constructor. The default value is null.
        private IList _constructorParameters;
        public IList ConstructorParameters { get {
            if (_constructorParameters == null)
            {
                _constructorParameters = new List<object>();
            }
            return _constructorParameters;
        }  }
    
        public string MethodName { get; set; }

        private IList _methodParameters;
        //
        // Summary:
        //     Gets the list of parameters to pass to the method.
        //
        // Returns:
        //     The list of parameters to pass to the method. The default is an empty list.
        public IList MethodParameters { get{
          if(_methodParameters==null){
              _methodParameters=new List<object>();
          }
            return _methodParameters;
        }}
        //
        // Summary:
        //     Gets or sets the object used as the binding source.
        //
        // Returns:
        //     The instance of the object constructed from System.Windows.Data.ObjectDataProvider.ObjectType
        //     and System.Windows.Data.ObjectDataProvider.ConstructorParameters, or the
        //     System.Windows.Data.DataSourceProvider of which the System.Windows.Data.DataSourceProvider.Data
        //     is used as the System.Windows.Data.ObjectDataProvider.ObjectInstance.
        //
        // Exceptions:
        //   System.InvalidOperationException:
        //     System.Windows.Data.ObjectDataProvider is assigned both an System.Windows.Data.ObjectDataProvider.ObjectType
        //     and an System.Windows.Data.ObjectDataProvider.ObjectInstance; only one is
        //     allowed.
        public object ObjectInstance { get; set; }
        //
        // Summary:
        //     Gets or sets the type of object to create an instance of.
        //
        // Returns:
        //     This property is null when the System.Windows.Data.ObjectDataProvider is
        //     uninitialized or explicitly set to null. If System.Windows.Data.ObjectDataProvider.ObjectInstance
        //     is assigned, System.Windows.Data.ObjectDataProvider.ObjectType returns the
        //     type of the object or null if the object is null. The default value is null.
        //
        // Exceptions:
        //   System.InvalidOperationException:
        //     System.Windows.Data.ObjectDataProvider is assigned both an System.Windows.Data.ObjectDataProvider.ObjectType
        //     and an System.Windows.Data.ObjectDataProvider.ObjectInstance; only one is
        //     allowed.
        public Type ObjectType { get; set; }
        private void SetObjectInstance()
        {
            try
            {
                if (ConstructorParameters.Count == 0)
                {
                    ObjectInstance = Activator.CreateInstance(ObjectType);
                }
                else
                {
                    Type[] pTypes = new Type[ConstructorParameters.Count];
                    for (int i = 0; i < ConstructorParameters.Count; i++)
                    {
                        pTypes[i] = ConstructorParameters[i].GetType();
                    }
                    ConstructorInfo mInfo = ObjectType.GetConstructor(pTypes);

                    object[] pms = new object[ConstructorParameters.Count];
                    for (int i = 0; i < ConstructorParameters.Count; i++)
                    {
                        pms[i] = ConstructorParameters[i];
                    }
                    ObjectInstance = mInfo.Invoke(pms);
                }
            }
            catch (System.Exception ex)
            {
                throw new Exception.DataBinderException("ObjectDataProvider---"+ex.Message, ex);
            }
        }
        private object CallMethod()
        {
            try
            {
                if (string.IsNullOrEmpty(MethodName))
                {
                    return null;
                }
                MethodInfo minfo = ObjectType.GetMethod(MethodName);

                if (MethodParameters.Count == 0)
                {
                    return minfo.Invoke(ObjectInstance, null);
                }
                else
                {
                    object[] pms = new object[MethodParameters.Count];
                    for (int i = 0; i < MethodParameters.Count; i++)
                    {
                        pms[i] = MethodParameters[i];
                    }
                    return minfo.Invoke(ObjectInstance, pms);
                }
            }
            catch (System.Exception ex)
            {
                throw new Exception.DataBinderException("ObjectDataProvider---" + ex.Message, ex);
            }

        }
        protected override void BeginQuery()
        {
            
            if (ObjectInstance == null)
            {
                SetObjectInstance();
            }
            if(string.IsNullOrEmpty(MethodName)){
                 _data=ObjectInstance;
                return;
            }else{
                   _data=  CallMethod();
            }

        }
    
    }
}
